/**
 Dssv.h
 
 \file
 Declaration of class Dssv.
 
 \author Thomas Burton 
 \date 3/13/12
 \copyright 2012 BNL. All rights reserved.
 */

#ifndef _Dssv_H_
#define _Dssv_H_

#include <map>
#include <string>
#include <vector>

#include <Rtypes.h>

#ifdef USING_LHAPDF
#include <LHAPDF/LHAPDF.h>
#else
#include "tppmc/Enumerations.h"
#endif

#include "tppmc/PartonContent.h"
#include "tppmc/PartonDistribution.h"

namespace tppmc {

   class Parton;

   /**
    DSSV longitudinally polarised (helicity) parton distributions.
    
    Reference: arXiv:0804:0422 [hep-ph]
    "Global Analysis of Helicity Parton Densities and their Uncertainties".
    
    C++ rewrite of the FORTRAN DSSVFIT and DSSVINI routines.
    */
   struct Dssv : public PartonDistribution {
      
      /**
       Constructor.
       Initialises grids (equivalent to Fortran DSSVINI).
       */
      Dssv();

      /** Destructor */
      virtual ~Dssv();

      /**
       Computes the helicity density of all parton flavours at the x of the
       input Parton and the requested scale Q<sup>2</sup>.
       The value of the distribution (NOT x times the distribution) is
       computed. Note that this differs from the Fortran DSSVFIT routine.
       Flavours which are not supported (see Supports()) have value = 0.
      */
      virtual void Evaluate(const Parton&, double scale,
                            PartonContent& values) const;

      /**
       Computes the helicity density of a single parton flavour at the x of the
       input Parton and the requested scale Q<sup>2</sup>.
       The value of the distribution (NOT x times the distribution) is
       returned. Note that this differs from the Fortran DSSVFIT routine.
       Flavours which are not supported (see Supports()) return 0.
       */
      virtual double Evaluate(const Parton&, double scale,
                              LHAPDF::Flavour) const;

      /**
       Returns true if the Parton type is supported.
       DSSV supports light quarks and gluons.
      */
      virtual bool Supports(const Parton&) const;
      
      /** Returns a string describing the distribution */
      virtual std::string Name() const;
      
      virtual double GetXMin() const;

      virtual double GetXMax() const;

      virtual double GetQ2Min() const;

      virtual double GetQ2Max() const;
      
   protected:
      
      unsigned GetNGridPointsQ2() { return smNGridPointsQ2; }
      unsigned GetNGridPointsX() { return smNGridPointsX; }
      
      typedef std::vector<double> Array;
      typedef std::vector<Array> Grid;
      
      // Methods:
      
      virtual bool InitialiseGrids();
      virtual double Interpolate( double, double, int ) const;
      
      // Static members:
      
      static const unsigned smNGridPointsQ2 = 30;
      static const unsigned smNGridPointsX = 47;
      
      // Members:
      
      Array mGridPointsQ2;
      Array mGridPointsX;
      // mGridPointsXQ2 stores the log of the known x points followed immediately
      // by log of the Q2 points (i.e. has length N_x + N_Q2).
      Array mGridPointsXQ2;
      
      std::vector<int> mGridDimensions;
      
      std::map<int, Grid> mPartonGrids;
      
      std::map<int, Array> mInterpolationGrids;

      ClassDef(tppmc::Dssv, 1)
   };

   inline double Dssv::GetXMin() const { return 1.0E-5; }

   inline double Dssv::GetXMax() const { return 1.0; }

   inline double Dssv::GetQ2Min() const { return 0.8; }

   inline double Dssv::GetQ2Max() const { return 1.0E6; }
   
} // namespace tppmc

#endif
